package logic.algorithm.aco;

import javax.swing.JFrame;
import logic.objects.Connection;
import logic.objects.Problem;
import logic.service.PheromonService;

public class MaxMinAS extends AntSystem {

	double tauMax;
	double tauMin;

	public MaxMinAS(Problem problem, JFrame frame) {
		super(problem, frame);
	}

	@Override
	protected void initializeParameters() {
		beta = 5.0;
		alpha = 1.0;
		roh = 0.5;
		tau0 = (1) / (roh * PheromonService
				.getNearestNeighborShortedTourValue(problem));
		tauMax = 1.0 / (tau0 * problem.getNodes().size());
		updateTauMin();
	}

	@Override
	protected void updatePheromon() {
		for (int i = 0; i < problem.getConnections().getSizeX(); i++) {
			for (int j = 0; j < problem.getConnections().getSizeY(); j++) {
				if (i != j) {
					Connection con = problem.getConnections().get(i, j);
					con.setPheromon(con.getPheromon() * (1.0 - roh));
				}
			}
		}
		updatePheromonByAnt(getBestSolutionAnt(), 1.0);
		updateRange();
		checkPheromonRange();
		problem.getConnections().updateMaxPheromon();
	}

	protected void checkPheromonRange() {
		for (int i = 0; i < problem.getConnections().getSizeX(); i++) {
			for (int j = 0; j < problem.getConnections().getSizeY(); j++) {
				if (i != j) {
					Connection con = problem.getConnections().get(i, j);
					if (con.getPheromon() > tauMax)
						con.setPheromon(tauMax);
					if (con.getPheromon() < tauMin)
						con.setPheromon(tauMin);
				}
			}
		}
	}

	protected void updateRange() {
		updateTauMax();
		updateTauMin();
	}

	private void updateTauMax() {
		tauMax = 1.0 / getBestTourSoFarValue();
	}

	private void updateTauMin() {
		Double n = (double) problem.getNodes().size();
		Double wurzel = Math.pow(0.05, 1.0 / n);
		tauMin = (tauMax * (1.0 - wurzel)) / (((n / 2.0) - 1.0) * wurzel);
	}

	public Ant getBestSolutionAnt() {
		int minIndex = 0;
		double length = Double.MAX_VALUE;
		for (int i = 0; i < ants.size(); i++) {
			if (length > ants.get(i).getTourLength()) {
				length = ants.get(i).getTourLength();
				minIndex = i;
			}
		}
		return ants.get(minIndex);
	}
}
